package vtc;

import java.util.*;

import com.ib.client.*;

public class IBBroker implements EWrapper 
{
	EClientSocket   client_;
	int nextValidOrderId_;
	double	netLiquidation_;
	double cashBalance_;
	double buyingPower_;
	String baseCurrency_;
	Map<Integer, DataEventIB> dataMap_;
	
	IBBroker()
	{
		client_ = new EClientSocket(this);
		baseCurrency_ = "USD";
		dataMap_ = new HashMap<Integer, DataEventIB>();
	}
    
	public void error(Exception e) 
    {
		System.out.print("ERROR: " + e.getMessage() + "\n");
    }

    public void error(String str) 
    {
    	System.out.print("ERROR: " + str + "\n");
    }

    public void error(int id, int errorCode, String errorMsg) 
    {
    	System.out.print("ERROR: " + errorMsg + "\n");
    }

    public void connectionClosed() 
    {
    }

    synchronized public void tickPrice(int tickerId, int field, double price, int canAutoExecute) 
    {
    	if(!dataMap_.containsKey(tickerId))
    	{
    		DataEventIB event = new DataEventIB();
    		dataMap_.put(tickerId, event);
    	}
    	DataEventIB event = dataMap_.get(tickerId);
    	event.setTickPrice(field, price);
    }
    

    synchronized public void tickSize(int tickerId, int field, int size) 
    {
    	if(!dataMap_.containsKey(tickerId))
    	{
    		DataEventIB event = new DataEventIB();
    		dataMap_.put(tickerId, event);
    	}
    	DataEventIB event = dataMap_.get(tickerId);
    	event.setTickSize(field, size);
    }

    public void tickOptionComputation(int tickerId, int field, double impliedVol, double delta, double modelPrice, double pvDividend) 
    {
    }

    public void tickGeneric(int tickerId, int tickType, double value) 
    {
    }

    public void tickString(int tickerId, int tickType, String value) 
    {
    	if(!dataMap_.containsKey(tickerId))
    	{
    		DataEventIB event = new DataEventIB();
    		dataMap_.put(tickerId, event);
    	}
    	DataEventIB event = dataMap_.get(tickerId);
    	event.setTickString(tickType, value);
    }

    public void tickEFP(int tickerId, int tickType, double basisPoints, String formattedBasisPoints, double impliedFuture, int holdDays, String futureExpiry, double dividendImpact, double dividendsToExpiry) 
    {
    }

    public void orderStatus(int orderId, String status, int filled, int remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, String whyHeld) 
    {
    	System.out.print("Status: " + status + "\n");
    }

    public void openOrder(int orderId, Contract contract, Order order, OrderState orderState) 
    {
    }

    public void updateAccountValue(String key, String value, String currency, String accountName) 
    {
    	if(key.equals("NetLiquidation"))
    	{
    		System.out.print("key: " + key + " value: " + value + " currency: " + currency +  " account: "+ accountName + "\n");
    		netLiquidation_ = Double.parseDouble(value);
    		baseCurrency_ = currency;
    	}
    	else if(key.equals("CashBalance") && currency.equals("BASE"))
    	{
    		System.out.print("key: " + key + " value: " + value + " currency: " + currency +  " account: "+ accountName + "\n");
    		cashBalance_ = Double.parseDouble(value);
    	}
    	else if(key.equals("BuyingPower"))
    	{
    		System.out.print("key: " + key + " value: " + value + " currency: " + currency +  " account: "+ accountName + "\n");
    		buyingPower_ = Double.parseDouble(value);
    	}
    }

    public void updatePortfolio(Contract contract, int position, double marketPrice, double marketValue, double averageCost, double unrealizedPNL, double realizedPNL, String accountName) 
    {
    	;
    }

    public void updateAccountTime(String timeStamp) 
    {
    	;
    }

    public void nextValidId(int orderId) 
    {
    	nextValidOrderId_ = orderId;
    }

    public void contractDetails(ContractDetails contractDetails) 
    {
    }

    public void bondContractDetails(ContractDetails contractDetails) 
    {
    }

    public void execDetails(int orderId, Contract contract, Execution execution) 
    {
    }

    public void updateMktDepth(int tickerId, int position, int operation, int side, double price, int size) 
    {
    }

    public void updateMktDepthL2(int tickerId, int position, String marketMaker, int operation, int side, double price, int size) 
    {
    }

    public void updateNewsBulletin(int msgId, int msgType, String message, String origExchange) 
    {
    }

    public void managedAccounts(String accountsList) 
    {
    	System.out.print("accountsList: " + accountsList + "\n");
    }
    
    public void receiveFA(int faDataType, String xml) 
    {
    }

    public void historicalData(int reqId, String date, double open, double high, double low, double close, int volume, int count, double WAP, boolean hasGaps) 
    {
    }

    public void scannerParameters(String xml) 
    {
    }

    public void scannerData(int reqId, int rank, ContractDetails contractDetails, String distance, String benchmark, String projection, String legsStr) 
    {
    }

    public void scannerDataEnd(int reqId) 
    {
    }

    public void realtimeBar(int reqId, long time, double open, double high, double low, double close, long volume, double wap, int count) 
    {
    	System.out.print("reqId:"+reqId+" time:"+time+" open:"+open+" high:"+high+" low:"+low+" close:"+close+" volume:"+volume+" wap:"+wap+" count:"+count+"\n");
    }

    public void currentTime(long time) 
    {
    }
    
    /* Usable interface */
    
    synchronized int getNextValidId()
    {
    	return nextValidOrderId_++;
    }
    
    public void connect(String ip, int port, int clientId)
    {
    	client_.eConnect( ip, port, clientId);
        if (client_.isConnected())
        {
        	System.out.print("Connected to Tws server version " + client_.serverVersion() + " at " + client_.TwsConnectionTime());
        }
    }
    
    void disconnect() 
    {
        client_.eDisconnect();
    }
    
    boolean isConnected()
    {
    	return client_.isConnected();
    }
    
    void placeOrder(int id, Contract contract, Order order) 
    {
        client_.placeOrder(id, contract, order);
    }

    void cancelOrder(int id) 
    {
    	client_.cancelOrder(id);
    }
    
    void  reqAllOpenOrders() 
    {
    	client_.reqAllOpenOrders();
    }
    
    void  setServerLogging(int logLevel)
    {
        client_.setServerLogLevel(logLevel);
    }
    
    void reqManagedAccts()
    {
    	client_.reqManagedAccts();
    }
    
    void reqAccountUpdates(boolean subscribe, String acctCode)
    {
    	client_.reqAccountUpdates(subscribe, acctCode);
    }

    double getCashBalance()
    {
    	return cashBalance_;
    }
    
    double getNetLiquidation()
    {
    	return netLiquidation_;
    }
    
    void reqRealTimeBars(int tickerId, Contract contract, int barSize, String whatToShow, boolean useRTH)
    {
    	client_.reqRealTimeBars(tickerId, contract, barSize, whatToShow, useRTH);
    }
    
    void reqMktData(int tickerId, Contract contract, String genericTickList, boolean snapshot)
    {
    	client_.reqMktData(tickerId, contract, genericTickList, snapshot);
    }
    
    synchronized DataEventIB getMktData(int tickerId)
    {
    	if(!dataMap_.containsKey(tickerId))
    	{
    		return null;
    	}
    	DataEventIB event = dataMap_.get(tickerId);
    	return event;
    }
    

}
